// Base.cpp: Nan Dun
#include "Base.h"

Base::Base()
{
	name = new string("Base");
	id = N;
	N++;
}

Base::Base(string s)
{
	name = new string(s);
	id = N;
	N++;
}

Base::Base(int i)
{
	name = new string("Base");
	id = i;
	N++;
}

Base::Base(string s, int i)
{
	name = new string(s);
	id = i;
	N++;
}

Base::~Base()
{
	delete name;
	N--;
}

void Base::set(string s)
{
	name->assign(s);
}

void Base::set(int i)
{
	id = i;
}

void Base::set(string s, int i)
{
	name->assign(s);
	id = i;
}

void Base::setToken(int t)
{
    base_token = t;
}

//Q: static int Base::getN(void) does not work, why?
int Base::getN(void)
{
	return N;
}

string Base::getName(void) const
{	
	string temp = *name;
	return temp;
}

int Base::getId(void) const
{
	return id;
}

int Base::getToken(void) const
{
    return base_token;
}

void Base::print(void)
{
	cout << "Hello from " << *name << ": " << base_token << " tokens, " << \
        id << " of " << N << " objects." << endl;
}

Base Base::operator+(Base& cls)
{
	Base temp;
	temp.set(*name + "+" + cls.getName(), N);
	return temp;
}

Base Base::operator-(Base& cls)
{
	Base temp;
	temp.set(*name + "-" + cls.getName(), N);
	return temp;
}

Base Base::operator*(const Base& cls)
{
    Base temp;
	temp.set(*name + "+" + cls.getName(), N);
    temp.setToken(base_token * cls.getToken());
    return temp;
}
//Q: Define operator* and operator/, then test

Base Base::operator/(Base& cls)
{
    Base temp;
	temp.set(*name + "/" + cls.getName(), N);
	return temp;
}
Base& Base::operator=(const Base& cls)
{
	if (this != &cls) {
		set(cls.getName());
	}
	return *this;
}

// friend function and class
void BaseFriend::printOther(Base& cls)
{
	cout << "Hello from BaseFriend " << *(cls.name) << ": " << cls.id << " of " \
		 << cls.N << " objects." << endl;
}

void friendPrint(Base& cls)
{
	cout << "Hello from friend " << *(cls.name) << ":" << cls.base_token <<
        " tokens, " << cls.id << " of " << cls.N << " objects." << endl;
}

ostream& operator<<(ostream& os, const Base& cls)
{
	os << "Hello from " << *(cls.name) << ':' << cls.id << " of " << cls.N
       << " objects.";
  	return os;
}

istream& operator>>(istream& is, Base& cls)
{
	return is;
}
